package org.lansir.af.ui;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jivesoftware.smack.packet.Presence.Mode;
import org.jivesoftware.smack.util.StringUtils;
import org.lansir.af.R;
import org.lansir.af.gtalk.GtalkApplication;
import org.lansir.af.gtalk.providers.AvatarProvider;
import org.lansir.af.gtalk.service.Contact;
import org.lansir.af.gtalk.service.Message;
import org.lansir.af.gtalk.service.PresenceAdapter;
import org.lansir.af.gtalk.service.aidl.IChat;
import org.lansir.af.gtalk.service.aidl.IChatManager;
import org.lansir.af.gtalk.service.aidl.IChatManagerListener;
import org.lansir.af.gtalk.service.aidl.IGtalkRosterListener;
import org.lansir.af.gtalk.service.aidl.IMessageListener;
import org.lansir.af.gtalk.service.aidl.IRoster;
import org.lansir.af.gtalk.service.aidl.IXmppFacade;
import org.lansir.af.gtalk.ui.dialogs.builders.ChatList;
import org.lansir.af.gtalk.utils.GtalkBroadcastReceiver;
import org.lansir.af.gtalk.utils.Status;

import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.text.util.Linkify;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ChatFragment extends CommonFragment implements TextView.OnEditorActionListener {
	private static final String TAG = "ChatFragment";
	private static final Intent SERVICE_INTENT = new Intent();

	static {
		SERVICE_INTENT.setComponent(new ComponentName("org.lansir.af", "org.lansir.af.gtalk.GtalkService"));
	}
	private Handler mHandler = new Handler();

	private IRoster mRoster;
	private Contact mContact;

	private TextView mContactNameTextView;
	private TextView mContactStatusMsgTextView;
	private TextView mContactChatState;
	private ImageView mContactStatusIcon;
	private LayerDrawable mAvatarStatusDrawable;
	private ListView mMessagesListView;
	private EditText mInputField;
	private Button mSendButton;
	private final Map<Integer, Bitmap> mStatusIconsMap = new HashMap<Integer, Bitmap>();

	private final List<MessageText> mListMessages = new ArrayList<MessageText>();

	private IChat mChat;
	private IChatManager mChatManager;
	private final IMessageListener mMessageListener = new OnMessageListener();
	private final IChatManagerListener mChatManagerListener = new ChatManagerListener();
	private MessagesListAdapter mMessagesListAdapter = new MessagesListAdapter();

	private final ServiceConnection mConn = new GtalkServiceConnection();
	private final GtalkBroadcastReceiver mBroadcastReceiver = new GtalkBroadcastReceiver();
	private final GtalkRosterListener mGtalkRosterListener = new GtalkRosterListener();
	private IXmppFacade mXmppFacade;
	private String mCurrentAvatarId;
	private boolean mBinded;
	private boolean mCompact;

	/**
	 * {@inheritDoc}.
	 */
	@Override
	public void onCreate(Bundle savedBundle) {
		super.onCreate(savedBundle);
		getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter(GtalkBroadcastReceiver.Gtalk_CONNECTION_CLOSED));
		SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
		mCompact = settings.getBoolean(GtalkApplication.USE_COMPACT_CHAT_UI_KEY, false);
		this.setHasOptionsMenu(true);

		prepareIconsStatus();
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View viewRoot = null;
		// UI
		if (!mCompact) {
			viewRoot = inflater.inflate(R.layout.chat, null);
			mContactNameTextView = (TextView) viewRoot.findViewById(R.id.chat_contact_name);
			mContactStatusMsgTextView = (TextView) viewRoot.findViewById(R.id.chat_contact_status_msg);
			mContactChatState = (TextView) viewRoot.findViewById(R.id.chat_contact_chat_state);
			mContactStatusIcon = (ImageView) viewRoot.findViewById(R.id.chat_contact_status_icon);
			mAvatarStatusDrawable = (LayerDrawable) mContactStatusIcon.getDrawable();
			mAvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0);
		} else {
			viewRoot = inflater.inflate(R.layout.chat_compact, null);
		}
		mMessagesListView = (ListView) viewRoot.findViewById(R.id.chat_messages);
		mMessagesListView.setAdapter(mMessagesListAdapter);
		mInputField = (EditText) viewRoot.findViewById(R.id.chat_input);
		mInputField.setOnEditorActionListener(this);
		mInputField.requestFocus();
		mSendButton = (Button) viewRoot.findViewById(R.id.chat_send_message);
		mSendButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				sendMessage();
			}
		});

		return viewRoot;
	}

	@Override
	public void onResume() {
		super.onResume();
		mContact = new Contact(getActivity().getIntent().getData());
		if (!mBinded) {
			mBinded = getActivity().bindService(SERVICE_INTENT, mConn, Context.BIND_AUTO_CREATE);
		}
	}

	/**
	 * {@inheritDoc}.
	 */
	@Override
	public void onDestroy() {
		super.onDestroy();
		getActivity().unregisterReceiver(mBroadcastReceiver);
	}

	/**
	 * {@inheritDoc}.
	 */
	@Override
	public void onPause() {
		super.onPause();
		try {
			if (mChat != null) {
				mChat.setOpen(false);
				mChat.removeMessageListener(mMessageListener);
			}
			if (mRoster != null)
				mRoster.removeRosterListener(mGtalkRosterListener);
			if (mChatManager != null)
				mChatManager.removeChatCreationListener(mChatManagerListener);
		} catch (RemoteException e) {
			Log.e(TAG, e.getMessage());
		}
		if (mBinded) {
			getActivity().unbindService(mConn);
			mBinded = false;
		}
		mXmppFacade = null;
		mRoster = null;
		mChat = null;
		mChatManager = null;
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.chat, menu);
		super.onCreateOptionsMenu(menu, inflater);
	}

	/**
	 * {@inheritDoc}.
	 */
	@Override
	public final boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.chat_menu_close_chat:
			try {
				mChatManager.destroyChat(mChat);
			} catch (RemoteException e) {
				Log.e(TAG, e.getMessage());
			}
			this.finish();
			break;
		default:
			return false;
		}
		return true;
	}

	/**
	 * Change the displayed chat.
	 * 
	 * @param contact
	 *            the targeted contact of the new chat
	 * @throws RemoteException
	 *             If a Binder remote-invocation error occurred.
	 */
	private void changeCurrentChat(Contact contact) throws RemoteException {
		if (mChat != null) {
			mChat.setOpen(false);
			mChat.removeMessageListener(mMessageListener);
		}
		Log.v(TAG, "changeCurrentChat");
		mChat = mChatManager.getChat(contact);
		if (mChat != null) {
			mChat.setOpen(true);
			mChat.addMessageListener(mMessageListener);
			mChatManager.deleteChatNotification(mChat);
		} else {
			// Log.v(TAG, "changeCurrentChat:getJIDFromRes:" +
			// mContact.getJIDWithRes());
			// mChat = mChatManager.createChat(mContact, mMessageListener);
			// mChat.setOpen(true);
			// Log.v(TAG, "changeCurrentChat:null");
		}
		mContact = mRoster.getContact(contact.getJID());
		String res = contact.getSelectedRes();
		if (mContact == null)
			mContact = contact;
		if (!"".equals(res)) {
			mContact.setSelectedRes(res);
		}
		updateContactInformations();
		updateContactStatusIcon();

		playRegisteredTranscript();
	}

	/**
	 * Get all messages from the current chat and refresh the activity with
	 * them.
	 * 
	 * @throws RemoteException
	 *             If a Binder remote-invocation error occurred.
	 */
	private void playRegisteredTranscript() throws RemoteException {
		mListMessages.clear();
		if (mChat != null) {
			List<MessageText> msgList = convertMessagesList(mChat.getMessages());
			mListMessages.addAll(msgList);
			mMessagesListAdapter.notifyDataSetChanged();
		}
	}

	/**
	 * Convert a list of Message coming from the service to a list of
	 * MessageText that can be displayed in UI.
	 * 
	 * @param chatMessages
	 *            the list of Message
	 * @return a list of message that can be displayed.
	 */
	private List<MessageText> convertMessagesList(List<Message> chatMessages) {
		List<MessageText> result = new ArrayList<MessageText>(chatMessages.size());
		String remoteName = mContact.getName();
		String localName = getString(R.string.chat_self);

		for (Message m : chatMessages) {
			String name = remoteName;
			String fromBareJid = StringUtils.parseBareAddress(m.getFrom());
			if (m.getBody() == null)
				continue;
			if (m.getType() == Message.MSG_TYPE_ERROR) {
				result.add(new MessageText(fromBareJid, name, m.getBody(), true, m.getTimestamp(), true));
			} else if (m.getType() == Message.MSG_TYPE_CHAT) {
				if (fromBareJid == null) { // nofrom or from == yours
					name = localName;
					fromBareJid = "";
					result.add(new MessageText(fromBareJid, name, m.getBody(), false, m.getTimestamp(), true));
				} else {
					result.add(new MessageText(fromBareJid, name, m.getBody(), false, m.getTimestamp(), false));

				}

			}
		}
		return result;
	}

	/**
	 * {@inheritDoc}.
	 */
	private final class GtalkServiceConnection implements ServiceConnection {

		/**
		 * Constructor.
		 */
		public GtalkServiceConnection() {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mXmppFacade = IXmppFacade.Stub.asInterface(service);
			try {
				mRoster = mXmppFacade.getRoster();
				if (mRoster != null)
					mRoster.addRosterListener(mGtalkRosterListener);
				mChatManager = mXmppFacade.getChatManager();
				if (mChatManager != null) {
					mChatManager.addChatCreationListener(mChatManagerListener);
					changeCurrentChat(mContact);

				}
			} catch (RemoteException e) {
				Log.e(TAG, e.getMessage());
			}
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onServiceDisconnected(ComponentName name) {
			mXmppFacade = null;
			try {
				mRoster.removeRosterListener(mGtalkRosterListener);
				mChatManager.removeChatCreationListener(mChatManagerListener);
			} catch (RemoteException e) {
				Log.e(TAG, e.getMessage());
			}
		}
	}

	/**
	 * {@inheritDoc}.
	 */
	private class GtalkRosterListener extends IGtalkRosterListener.Stub {

		/**
		 * Constructor.
		 */
		public GtalkRosterListener() {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onEntriesAdded(List<String> addresses) throws RemoteException {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onEntriesDeleted(List<String> addresses) throws RemoteException {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onEntriesUpdated(List<String> addresses) throws RemoteException {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void onPresenceChanged(final PresenceAdapter presence) throws RemoteException {
			if (mContact.getJID().equals(StringUtils.parseBareAddress(presence.getFrom()))) {
				mHandler.post(new Runnable() {
					@Override
					public void run() {
						mContact.setStatus(presence.getStatus());
						mContact.setMsgState(presence.getStatusText());
						updateContactInformations();
						updateContactStatusIcon();
					}
				});
			}
		}
	}

	/**
	 * {@inheritDoc}.
	 */
	private class OnMessageListener extends IMessageListener.Stub {

		/**
		 * Constructor.
		 */
		public OnMessageListener() {
		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void processMessage(IChat chat, final Message msg) throws RemoteException {
			Log.v(TAG, "process message:" + msg.getBody());
			final String fromBareJid = StringUtils.parseBareAddress(msg.getFrom());
			if (msg.getBody() != null && !"".equals(msg.getBody())) {
				mHandler.post(new Runnable() {

					@Override
					public void run() {
						if (msg.getType() == Message.MSG_TYPE_ERROR) {
							mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(), true, msg.getTimestamp(), false));

						} else if (msg.getBody() != null) {

							mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(), false, msg.getTimestamp(), false));
						}
						mMessagesListAdapter.notifyDataSetChanged();
					}
				});
			}

		}

		/**
		 * {@inheritDoc}.
		 */
		@Override
		public void stateChanged(IChat chat) throws RemoteException {
			final String state = chat.getState();
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					String text = null;
					if ("active".equals(state)) {
						text = getActivity().getString(R.string.chat_state_active);
					} else if ("composing".equals(state)) {
						text = getActivity().getString(R.string.chat_state_composing);
					} else if ("gone".equals(state)) {
						text = getActivity().getString(R.string.chat_state_gone);
					} else if ("inactive".equals(state)) {
						text = getActivity().getString(R.string.chat_state_inactive);
					} else if ("paused".equals(state)) {
						text = getActivity().getString(R.string.chat_state_active);
					}
					if (!mCompact)
						mContactChatState.setText(text);
				}
			});

		}
	}

	/**
	 * Update the contact informations.
	 */
	private void updateContactInformations() {
		// Check for a contact name update
		String name = mContact.getName();
		String res = mContact.getSelectedRes();
		if (!"".equals(res))
			name += "(" + res + ")";
		if (!mCompact) {
			if (!(mContactNameTextView.getText().toString().equals(name)))
				mContactNameTextView.setText(name);
			// Check for a contact status message update
			if (!(mContactStatusMsgTextView.getText().toString().equals(mContact.getMsgState()))) {
				mContactStatusMsgTextView.setText(mContact.getMsgState());
				Linkify.addLinks(mContactStatusMsgTextView, Linkify.WEB_URLS);
			}
		} else {
			Mode m = Status.getPresenceModeFromStatus(mContact.getStatus());
			if (m == null)
				getActivity().setTitle(getString(R.string.chat_name) + " " + name + " (" + getString(R.string.contact_status_msg_offline) + ")");
			else
				getActivity().setTitle(getString(R.string.chat_name) + " " + name + " (" + m.name() + ")");
		}
	}

	/**
	 * Update the contact status icon.
	 */
	private void updateContactStatusIcon() {
		if (mCompact)
			return;
		String id = mContact.getAvatarId();
		if (id == null)
			id = "";
		Log.d(TAG, "update contact icon  : " + id);
		if (!id.equals(mCurrentAvatarId)) {
			Drawable avatar = getAvatarDrawable(mContact.getAvatarId());
			mAvatarStatusDrawable.setDrawableByLayerId(R.id.avatar, avatar);
			mCurrentAvatarId = id;
		}
		mContactStatusIcon.setImageLevel(mContact.getStatus());
	}

	/**
	 * Get a Drawable containing the avatar icon.
	 * 
	 * @param avatarId
	 *            the avatar id to retrieve or null to get default
	 * @return a Drawable
	 */
	private Drawable getAvatarDrawable(String avatarId) {
		Drawable avatarDrawable = null;
		if (avatarId != null) {
			Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build();
			InputStream in = null;
			try {
				try {
					in = getActivity().getContentResolver().openInputStream(uri);
					avatarDrawable = Drawable.createFromStream(in, avatarId);
				} finally {
					if (in != null)
						in.close();
				}
			} catch (IOException e) {
				Log.w(TAG, "Error while setting the avatar", e);
			}
		}
		if (avatarDrawable == null)
			avatarDrawable = getResources().getDrawable(R.drawable.gtalk_status_icon);
		return avatarDrawable;
	}

	/**
	 * Prepare the status icons map.
	 */
	private void prepareIconsStatus() {
		mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE, BitmapFactory.decodeResource(getResources(), android.R.drawable.presence_online));
		mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE_FOR_CHAT, BitmapFactory.decodeResource(getResources(), android.R.drawable.presence_online));
		mStatusIconsMap.put(Status.CONTACT_STATUS_AWAY, BitmapFactory.decodeResource(getResources(), android.R.drawable.presence_away));
		mStatusIconsMap.put(Status.CONTACT_STATUS_BUSY, BitmapFactory.decodeResource(getResources(), android.R.drawable.presence_busy));
		mStatusIconsMap.put(Status.CONTACT_STATUS_DISCONNECT, BitmapFactory.decodeResource(getResources(), android.R.drawable.presence_offline));
		mStatusIconsMap.put(Status.CONTACT_STATUS_UNAVAILABLE, BitmapFactory.decodeResource(getResources(), R.drawable.status_requested));
	}

	/**
	 * {@inheritDoc}.
	 */
	private class MessagesListAdapter extends BaseAdapter {

		/**
		 * Constructor.
		 */
		public MessagesListAdapter() {
		}

		/**
		 * Returns the number of messages contained in the messages list.
		 * 
		 * @return The number of messages contained in the messages list.
		 */
		@Override
		public int getCount() {
			return mListMessages.size();
		}

		/**
		 * Return an item from the messages list that is positioned at the
		 * position passed by parameter.
		 * 
		 * @param position
		 *            The position of the requested item.
		 * @return The item from the messages list at the requested position.
		 */
		@Override
		public Object getItem(int position) {
			return mListMessages.get(position);
		}

		/**
		 * Return the id of an item from the messages list that is positioned at
		 * the position passed by parameter.
		 * 
		 * @param position
		 *            The position of the requested item.
		 * @return The id of an item from the messages list at the requested
		 *         position.
		 */
		@Override
		public long getItemId(int position) {
			return position;
		}

		/**
		 * Return the view of an item from the messages list.
		 * 
		 * @param position
		 *            The position of the requested item.
		 * @param convertView
		 *            The old view to reuse if possible.
		 * @param parent
		 *            The parent that this view will eventually be attached to.
		 * @return A View corresponding to the data at the specified position.
		 */
		public View getView(int position, View convertView, ViewGroup parent) {

			MessageText msg = mListMessages.get(position);
			ViewHolder viewHolder;

			LayoutInflater inflater = getActivity().getLayoutInflater();
			if (msg.isSelf()) {
				convertView = inflater.inflate(R.layout.chat_msg_row_send, null);
			} else {
				convertView = inflater.inflate(R.layout.chat_msg_row_reply, null);
			}
			viewHolder = new ViewHolder();
			viewHolder.tvChatMessageName = (TextView) convertView.findViewById(R.id.tvChatMessageName);
			viewHolder.tvChatMessageText = (TextView) convertView.findViewById(R.id.tvChatMessageText);
			viewHolder.tvChatMessageDate = (TextView) convertView.findViewById(R.id.tvChatMessageDate);

			DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);

			viewHolder.tvChatMessageName.setError(null);

			viewHolder.tvChatMessageText.setText(msg.getMessage());
			registerForContextMenu(viewHolder.tvChatMessageText);

			String date = df.format(msg.getTimestamp());
			viewHolder.tvChatMessageDate.setText(date);
			if (msg.isError()) {
				String err = getString(R.string.chat_error);
				viewHolder.tvChatMessageName.setText(err);
				viewHolder.tvChatMessageName.setTextColor(Color.RED);
				viewHolder.tvChatMessageName.setError(err);
			}
			return convertView;
		}

		private class ViewHolder {
			public TextView tvChatMessageName;
			public TextView tvChatMessageText;
			public TextView tvChatMessageDate;
		}
	}

	/**
	 * Class which simplify an Xmpp text message.
	 * 
	 * @author Jean-Manuel Da Silva <dasilvj at Gtalk-project dot com>
	 */
	private class MessageText {
		private String mBareJid;
		private String mName;
		private String mMessage;
		private boolean mIsError;
		private Date mTimestamp;
		private boolean mIsSelf;

		/**
		 * Constructor.
		 * 
		 * @param bareJid
		 *            A String containing the bare JID of the message's author.
		 * @param name
		 *            A String containing the name of the message's author.
		 * @param message
		 *            A String containing the message.
		 * @param isError
		 *            if the message is an error message.
		 * @param date
		 *            the time of the message.
		 */
		public MessageText(final String bareJid, final String name, final String message, final boolean isError, final Date date, final boolean isSelf) {
			mBareJid = bareJid;
			mName = name;
			mMessage = message;
			mIsError = isError;
			mTimestamp = date;
			mIsSelf = isSelf;
		}

		/**
		 * JID attribute accessor.
		 * 
		 * @return A String containing the bare JID of the message's author.
		 */
		public String getBareJid() {
			return mBareJid;
		}

		/**
		 * Name attribute accessor.
		 * 
		 * @return A String containing the name of the message's author.
		 */
		public String getName() {
			return mName;
		}

		/**
		 * Message attribute accessor.
		 * 
		 * @return A String containing the message.
		 */
		public String getMessage() {
			return mMessage;
		}

		/**
		 * JID attribute mutator.
		 * 
		 * @param bareJid
		 *            A String containing the author's bare JID of the message.
		 */
		@SuppressWarnings("unused")
		public void setBareJid(String bareJid) {
			mBareJid = bareJid;
		}

		/**
		 * Name attribute mutator.
		 * 
		 * @param name
		 *            A String containing the author's name of the message.
		 */
		@SuppressWarnings("unused")
		public void setName(String name) {
			mName = name;
		}

		/**
		 * Message attribute mutator.
		 * 
		 * @param message
		 *            A String containing a message.
		 */
		public void setMessage(String message) {
			mMessage = message;
		}

		/**
		 * Get the message type.
		 * 
		 * @return true if the message is an error message.
		 */
		public boolean isError() {
			return mIsError;
		}

		/**
		 * Set the Date of the message.
		 * 
		 * @param date
		 *            date of the message.
		 */
		public void setTimestamp(Date date) {
			mTimestamp = date;
		}

		/**
		 * Get the Date of the message.
		 * 
		 * @return if it is a delayed message get the date the message was
		 *         sended.
		 */
		public Date getTimestamp() {
			return mTimestamp;
		}

		public boolean isSelf() {
			return mIsSelf;
		}

		public void setIsSelf(boolean mIsSelf) {
			this.mIsSelf = mIsSelf;
		}

	}

	/**
	 * {@inheritDoc}.
	 */
	@Override
	public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
		if (v == mInputField && actionId == EditorInfo.IME_ACTION_SEND) {
			sendMessage();
			return true;
		}
		return false;
	}

	/**
	 * Send an XMPP message.
	 */
	private void sendMessage() {
		final String inputContent = mInputField.getText().toString();

		if (!"".equals(inputContent)) {
			Message msgToSend = new Message(mContact.getJIDWithRes(), Message.MSG_TYPE_CHAT);
			msgToSend.setBody(inputContent);

			try {
				if (mChat == null) {
					Log.v(TAG, "CreateChat");
					mChat = mChatManager.createChat(mContact, mMessageListener);
					mChat.setOpen(true);
				}
				mChat.sendMessage(msgToSend);
			} catch (RemoteException e) {
				Log.e(TAG, e.getMessage());
			}

			final String self = getString(R.string.chat_self);

			mListMessages.add(new MessageText(self, self, inputContent, false, new Date(), true));
			mMessagesListAdapter.notifyDataSetChanged();
			mInputField.setText(null);
		}
	}

	/**
	 * This class is in charge of getting the new chat in the activity if
	 * someone talk to you.
	 */
	private class ChatManagerListener extends IChatManagerListener.Stub {

		/**
		 * Constructor.
		 */
		public ChatManagerListener() {
		}

		@Override
		public void chatCreated(IChat chat, boolean locally) {
			if (locally)
				return;
			try {
				Log.e(TAG, "ChatFragment:chatCreated");
				String contactJid = mContact.getJIDWithRes();
				String chatJid = chat.getParticipant().getJIDWithRes();
				if (chatJid.equals(contactJid)) {
					// This should not be happened but to be sure
					if (mChat != null) {
						mChat.setOpen(false);
						mChat.removeMessageListener(mMessageListener);
					}
					mChat = chat;
					mChat.setOpen(true);
					mChat.addMessageListener(mMessageListener);
					mChatManager.deleteChatNotification(mChat);
				}
			} catch (RemoteException ex) {
				Log.e(TAG, "A remote exception occurs during the creation of a chat", ex);
			}
		}
	}
}
